package com.djbx.points.member.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.djbx.points.common.core.exception.BusinessException;
import com.djbx.points.common.core.utils.BeanListUtils;
import com.djbx.points.common.core.utils.PageList;
import com.djbx.points.common.core.utils.ResponseCode;
import com.djbx.points.common.core.utils.ServiceResponse;
import com.djbx.points.coupon.api.client.CouponClient;
import com.djbx.points.coupon.api.dto.CouponInDTO;
import com.djbx.points.member.api.dto.MemberInDTO;
import com.djbx.points.member.api.dto.MemberOutDTO;
import com.djbx.points.member.entity.MemberEntity;
import com.djbx.points.member.mapper.MemberMapper;
import com.djbx.points.member.service.MemberService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
@CacheConfig(cacheNames="Caches.Member")
public class MemberServiceImpl implements MemberService {

    @Autowired
    private CouponClient couponClient;

    @Autowired
    private MemberMapper memberMapper;

    @Override
    public ServiceResponse<MemberOutDTO> getMember(Long id) {
        MemberEntity member = memberMapper.selectById(id);
        MemberOutDTO out = BeanListUtils.copyProperties(member, MemberOutDTO::new);
        return new ServiceResponse<MemberOutDTO>().setData(out);
    }

    @Override
    public ServiceResponse<MemberOutDTO> getList(MemberInDTO inDTO) {
        LambdaQueryWrapper<MemberEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(!StringUtils.isBlank(inDTO.getNickname()), MemberEntity::getNickname, inDTO.getNickname());
        wrapper.like(!Objects.isNull(inDTO.getLevelId()), MemberEntity::getLevelId, inDTO.getLevelId());
        wrapper.ne(true, MemberEntity :: getStatus, -1);
        wrapper.orderByAsc(MemberEntity::getCreateTime);

        List<MemberEntity> entities = memberMapper.selectList(wrapper);
        List<MemberOutDTO> dtoList = BeanListUtils.copyListProperties(entities, MemberOutDTO::new);
        return new ServiceResponse<MemberOutDTO>().setList(dtoList);
    }

    @Override
    public ServiceResponse<MemberOutDTO> getPage(MemberInDTO inDTO) {
        IPage<MemberEntity> page = new Page<>();
        page.setCurrent(inDTO.getCurrPage());
        page.setSize(inDTO.getPageSize());

        LambdaQueryWrapper<MemberEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(!StringUtils.isBlank(inDTO.getNickname()), MemberEntity::getNickname, inDTO.getNickname());
        wrapper.eq(!Objects.isNull(inDTO.getLevelId()), MemberEntity::getLevelId, inDTO.getLevelId());
        wrapper.ne(true, MemberEntity :: getStatus, -1);
        wrapper.orderByAsc(MemberEntity::getCreateTime);

        IPage<MemberEntity> entityPage = memberMapper.selectPage(page, wrapper);
        PageList<MemberOutDTO> dtoPage = BeanListUtils.copyPageProperties(entityPage, MemberOutDTO::new);
        return new ServiceResponse<MemberOutDTO>().setPageList(dtoPage);
    }

    @Override
    @CacheEvict(allEntries=true)
    @GlobalTransactional
    public ServiceResponse<Void> save(MemberInDTO memberVO) {

        // 构造优惠券信息
        log.info("Coupon服务调用开始");
        CouponInDTO couponInDTO = new CouponInDTO();
        couponInDTO.setCouponType(1);
        couponInDTO.setCouponImg("http://test.coupon.image/coupon.jpg");
        couponInDTO.setCouponName("100元减10元");
        couponInDTO.setNum(2);
        couponInDTO.setAmount(new BigDecimal(10L));
        couponInDTO.setPerLimit(3);
        couponInDTO.setMinPoint(new BigDecimal(100L));
        couponInDTO.setEndTime(LocalDate.now());
        couponInDTO.setUseType(3);
        couponInDTO.setNote("测试用");
        couponInDTO.setPublishCount(25);
        couponInDTO.setUseCount(10);
        couponInDTO.setReceiveCount(20);
        couponInDTO.setEnableEndTime(LocalDate.now());
        couponInDTO.setEnableStartTime(LocalDate.now());
        couponInDTO.setCode("tucddio");
        couponInDTO.setMemberLevel(1);
        couponInDTO.setPublish(1);

        ServiceResponse<Void> response = couponClient.save(couponInDTO);
        if(!response.isSuccess()){
            log.error("coupon保存失败，返回结果：{}", response);
            throw new BusinessException(ResponseCode.FAILED.getCode(), "Coupon保存失败");
        }
        log.info("Coupon服务调用结束");

        MemberEntity memberEntity = new MemberEntity();
        BeanUtils.copyProperties(memberVO, memberEntity);
        memberEntity.setStatus(1);
        memberMapper.insert(memberEntity);
//        if(memberVO.getGrowth() != null && memberVO.getGrowth() == 0){
//            //测试代码，当growth==0时，回滚，验证seata
//            throw new BusinessException(ResponseCode.FAILED.getCode(), "test");
//        }
        log.info("member信息已入库");

        return new ServiceResponse<>();
    }

    @Override
    @CacheEvict(allEntries=true)
    @GlobalTransactional
    public ServiceResponse<Void> update(MemberInDTO memberVO) {
        if(memberVO.getId() != null){
            MemberEntity memberEntity = new MemberEntity();
            BeanUtils.copyProperties(memberVO, memberEntity);

            LambdaUpdateWrapper<MemberEntity> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(!Objects.isNull(memberVO.getId()), MemberEntity::getId, memberVO.getId());

            memberMapper.update(memberEntity, wrapper);
            return new ServiceResponse<>();
        }
        return new ServiceResponse<>(ResponseCode.MISSING_REQUEST_PARAM_ERROR);
    }

    @Override
    @CacheEvict(allEntries=true)
    @GlobalTransactional
    public ServiceResponse<Void> delete(Long id) {
        //sharding在获取tablemeta时，会根据logictablename去查询，如果逻辑表名能like到其它表，则会出错
//        memberMapper.deleteById(id);

        MemberEntity memberEntity = new MemberEntity();
        memberEntity.setId(id);
        memberEntity.setStatus(-1);
        return new ServiceResponse<>();
    }
}
